import { PostProcessStage, Viewer } from 'cesium'
import * as Cesium from 'cesium'

/***
 * @class DEUGlobe.Scene.sceneEffects.weatherEffects
 * @category  场景
 * @classdesc 场景特效-天气特效
 * @param {Object} viewer -  Cesium.viewer。
 * @param {Object} options - 参数。
 * @param {String} options.name - 天气特效名称。
 * @param {String} options.type - 天气特效类型. (snow：雪 ， rain：雨，fog：雾,sun ,晴天)。
 */


class WeatherEffects{
  private viewer: Viewer;
   name:string;
   type:string;
  constructor(viewer:Viewer,options:  Partial<WeatherEffects> = {}){
    this.viewer = viewer
    this.name = options.name||'';
    this.type = options.type||'';
  }

  public setPostProcessStage(name:string,type:string):void{
    this.viewer.scene.postProcessStages.removeAll();
    this.name=name;
    this.type=type;
    let stage = this.getStage();
    let fs:string = '';
    if(stage == null){
      switch(this.type){
        case "snow":
          fs = this.fs_snow();
          break;
        case "rain":
          fs = this.fs_rain();
          break;
        case "fog":
          fs = this.fs_fog();
          break
      }
    }
    if(name!=='晴天'){
      stage = new PostProcessStage({
        name : this.name,
        fragmentShader:fs,
        uniforms : {
          color: Cesium.Color.fromAlpha(Cesium.Color.WHITE, 1.0),
        }
      });
      this.viewer.scene.postProcessStages.add(stage);
    }
  }


  private removePostProcessStage(){
    let stage =  this.getStage();
    if(stage){
      this.viewer.scene.postProcessStages.remove(stage);
    }
  }
 private getStage(){
    let stage = null;
    let  stages :any=  this.viewer.scene.postProcessStages;
    for(let i = 0;i<stages._stages.length;i++){
      let tmp = stages.get(i);
      if(tmp != undefined && tmp.name == this.name){
        stage = tmp;
        break;
      }
    }
    return stage;
  }
        private fs_snow() {
          return `#version 300 es
      precision mediump float;
      uniform sampler2D colorTexture;
      in vec2 v_textureCoordinates;
      out vec4 fragColor;

      float snow(vec2 uv, float scale) {
          float time = czm_frameNumber / 60.0;
          float w = smoothstep(1., 0., -uv.y * (scale / 10.));
          if (w < .1) return 0.;
          uv += time / scale;
          uv.y += time * 2. / scale;
          uv.x += sin(uv.y + time * .5) / scale;
          uv *= scale;
          vec2 s = floor(uv), f = fract(uv), p;
          float k = 3., d;
          p = .5 + .35 * sin(11. * fract(sin((s + p + scale) * mat2(7, 3, 6, 5)) * 5.)) - f;
          d = length(p);
          k = min(d, k);
          k = smoothstep(0., k, sin(f.x + f.y) * 0.01);
          return k * w;
      }

      void main(void) {
          vec2 resolution = czm_viewport.zw;
          vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);
          vec3 finalColor = vec3(0);
          float c = 0.0;
          c += snow(uv, 30.) * .0;
          c += snow(uv, 20.) * .0;
          c += snow(uv, 15.) * .0;
          c += snow(uv, 10.);
          c += snow(uv, 8.);
          c += snow(uv, 6.);
          c += snow(uv, 5.);
          finalColor = vec3(c);
          fragColor = mix(texture(colorTexture, v_textureCoordinates), vec4(finalColor, 1), 0.25);
      }`;
        }
        private fs_rain() {
          return `#version 300 es
      precision mediump float;
      uniform sampler2D colorTexture;
      in vec2 v_textureCoordinates;
      out vec4 fragColor;

      float hash(float x) {
          return fract(sin(x * 133.3) * 13.13);
      }

      void main(void) {
          float time = czm_frameNumber / 60.0;
          vec2 resolution = czm_viewport.zw;
          vec2 uv = (gl_FragCoord.xy * 2. - resolution.xy) / min(resolution.x, resolution.y);
          vec3 c = vec3(.6, .7, .8);
          float a = -.4;
          float si = sin(a), co = cos(a);
          uv *= mat2(co, -si, si, co);
          uv *= length(uv + vec2(0, 4.9)) * .3 + 1.;
          float v = 1. - sin(hash(floor(uv.x * 100.)) * 2.);
          float b = clamp(abs(sin(20. * time * v + uv.y * (5. / (2. + v)))) - .95, 0., 1.) * 20.;
          c *= v * b;
          vec4 baseColor=texture(colorTexture, v_textureCoordinates);
          fragColor = mix(baseColor, vec4(c, 1), 0.25);
      }`;
        }
  private fs_fog(){
    return 'uniform sampler2D colorTexture;\n'
      +'  uniform sampler2D depthTexture;\n'
      +'  in vec2 v_textureCoordinates;\n'
      +'  void main(void)\n'
      +'  {\n'
      +'      vec4 origcolor=texture(colorTexture, v_textureCoordinates);\n'
      +'      vec4 fogcolor=vec4(0.8,0.8,0.8,0.5);\n'
      +'      float depth = czm_readDepth(depthTexture, v_textureCoordinates);\n'
      +'      vec4 depthcolor=texture(depthTexture, v_textureCoordinates);\n'
      +'      float f=(depthcolor.r-0.22)/0.2;\n'
      +'      if(f<0.0) f=0.0;\n'
      +'      else if(f>1.0) f=1.0;\n'
      +'      out = mix(origcolor,fogcolor,0.8);\n'
      +'   }';
  }
}
export  default WeatherEffects
